package Or

import (
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"strings"
)

func (or TableInfoMeta) TriggerExist(s global.TablesMetaInfoInput) (result global.ObjectExistReturnResult, err error) {
	var f1 any
	var event = "[oracleTriggerExist]"
	for _, v := range []string{
		//"USER_TRIGGERS",
		"ALL_TRIGGERS",
		"DBA_TRIGGERS",
	} {
		result.BaseResult.Sql = fmt.Sprintf("select count(1) as \"sum\" from %v where OWNER = '%v' and TRIGGER_NAME='%v'", v, s.TableInfo.Schema, s.TableInfo.Table)
		if result.BaseResult.TimeOut, f1, err = ExecSelectSql(ExecSqlInputS{
			Ss:           s,
			Event:        event,
			SelectSqlStr: result.BaseResult.Sql,
			Expect:       ETL.Map,
		}); err != nil || f1 == nil {
			continue
		}
		if fmt.Sprintf("%v", f1.(map[string]any)["sum"]) == "1" {
			result.Result = true
		}
		break
	}
	return
}

func (or TableInfoMeta) TriggerName(s global.TablesMetaInfoInput) (result global.ObjectNameReturnResult, err error) {
	var f1 any
	var event = "[oracleTriggerName]"
	for _, v := range []string{
		//"USER_TRIGGERS",
		"ALL_TRIGGERS",
		"DBA_TRIGGERS",
	} {
		result.BaseResult.Sql = fmt.Sprintf("select TRIGGER_NAME from %v where  OWNER ='%v' %v",
			v, s.TableInfo.Schema, func() string {
				switch {
				case s.TableInfo.Table == "*":
					return ""
				case strings.Contains(s.TableInfo.Table, "%"):
					return fmt.Sprintf(" and TRIGGER_NAME like '%%%v%%'", s.TableInfo.Table)
				default:
					return fmt.Sprintf(" and TRIGGER_NAME = '%v'", s.TableInfo.Table)
				}
			}())
		if result.BaseResult.TimeOut, f1, err = ExecSelectSql(ExecSqlInputS{
			Ss:           s,
			Event:        event,
			SelectSqlStr: result.BaseResult.Sql,
			Expect:       ETL.StringGarth,
		}); err != nil || f1 == nil {
			continue
		}
		result.Result = f1.([]string)
		break
	}

	return
}
func TriggerPrintInfo(x *global.TriggerResultDefinition) (res string) {
	var (
		caseWhen, active, opportunity, objectScope string
	)
	if !strings.EqualFold(strings.TrimSpace(x.CaseWhen), "NULL") {
		caseWhen = fmt.Sprintf("WHEN (%v) ", x.CaseWhen)
	}
	switch {
	case strings.HasPrefix(strings.TrimSpace(x.TriggerType), "BEFORE"):
		active = "BEFORE"
		x.Timing = active
	case strings.HasPrefix(strings.TrimSpace(x.TriggerType), "AFTER"):
		active = "AFTER"
		x.Timing = active
	}
	switch x.MonitorEvent {
	case "INSERT":
		opportunity = fmt.Sprintf("%v %v ", active, x.MonitorEvent)
		objectScope = strings.ReplaceAll(x.TriggerType, active, "FOR")
		x.Orientation = strings.TrimSpace(strings.ReplaceAll(strings.TrimSpace(strings.ReplaceAll(x.TriggerType, active, "")), "EACH", ""))
	case "UPDATE":
		opportunity = fmt.Sprintf("%v %v ", active, x.MonitorEvent)
		objectScope = strings.ReplaceAll(x.TriggerType, active, "FOR")
		x.Orientation = strings.TrimSpace(strings.ReplaceAll(strings.TrimSpace(strings.ReplaceAll(x.TriggerType, active, "")), "EACH", ""))
	case "DELETE":
		opportunity = fmt.Sprintf("%v %v ", active, x.MonitorEvent)
		objectScope = strings.ReplaceAll(x.TriggerType, active, "FOR")
		x.Orientation = strings.TrimSpace(strings.ReplaceAll(strings.TrimSpace(strings.ReplaceAll(x.TriggerType, active, "")), "EACH", ""))
	default:
		opportunity = fmt.Sprintf("%v %v ", active, x.MonitorEvent)
		objectScope = strings.ReplaceAll(x.TriggerType, active, "FOR")
		x.Orientation = strings.TrimSpace(strings.ReplaceAll(strings.TrimSpace(strings.ReplaceAll(x.TriggerType, active, "")), "EACH", ""))
	}
	return fmt.Sprintf("CREATE OR REPLACE TRIGGER \"%v\".\"%v\" \n"+
		" %v ON \"%v\".\"%v\" \n"+
		" %v \n "+
		" %v \n"+
		" %v \n"+
		"COMMENT ON TRIGGER \"%v\".\"%v\" IS '%v';\n"+
		"ALTER TRIGGER \"%v\".\"%v\" %v;\n"+
		"/\n", x.Schema, x.Name,
		opportunity, x.MonitorSchema, x.MonitorTable,
		objectScope,
		caseWhen,
		x.Body,
		x.Schema, x.Name, x.Comment,
		x.Schema, x.Name, x.Status,
	)
}
func triggerDefinitionConvert(x global.TriggerResultDefinition) (convert global.TriggerDefinitionConvertS) {
	convert = global.TriggerDefinitionConvertS{
		Schema:       x.Schema,
		Name:         x.Name,
		TriggerType:  x.TriggerType,
		MonitorEvent: x.MonitorEvent,
		MonitorTable: x.MonitorTable,
		Timing:       x.Timing,
		Orientation:  x.Orientation,
		CaseWhen:     x.CaseWhen,
		Comment:      x.Comment,
		Body:         x.Body,
		Frequency:    x.Frequency,
		Status:       x.Status,
		Type:         x.Type,
		PrintInfo:    x.PrintInfo,
	}
	switch x.MonitorEvent {
	case "INSERT":
		convert.TriggerEventGarth = []string{"INSERT"}
	case "UPDATE":
		convert.TriggerEventGarth = []string{"UPDATE"}
	case "DELETE":
		convert.TriggerEventGarth = []string{"DELETE"}
	default:
		convert.TriggerEventGarth = strings.Split(strings.TrimSpace(x.MonitorEvent), "OR")
	}
	return
}
func (or SchemaObjectMeta) Trigger(s global.SchemaObjectInput) (result global.SchemaObjectReturnResult, err error) {
	var (
		f1    any
		x     global.TriggerResultDefinition
		event = "[oracleTrigger]"
	)
	for _, v := range []string{
		//"USER_TRIGGERS",
		"ALL_TRIGGERS",
		"DBA_TRIGGERS",
	} {
		result.BaseResult.Sql = fmt.Sprintf("SELECT\n"+
			"\t\"OWNER\" AS \"schema\",\n"+
			"\t\"TRIGGER_NAME\" AS \"name\",\n"+
			"\t\"TRIGGER_TYPE\" AS \"triggerType\",\n"+
			"\t\"TRIGGERING_EVENT\" AS \"monitorEvent\",\n"+
			"\t\"TABLE_OWNER\" AS \"monitorSchema\","+
			"\t\"TABLE_NAME\" AS \"monitorTable\",\n"+
			"\t\"WHEN_CLAUSE\" AS \"caseWhen\",\n"+
			"\t\"DESCRIPTION\" AS \"comment\",\n"+
			"\t\"TRIGGER_BODY\" AS \"body\",\n"+
			"\t\"FIRE_ONCE\" AS \"frequency\",\n"+
			"\t\"STATUS\" AS \"status\" \n"+
			"FROM\n"+
			"\t%v \n"+
			"WHERE 1 = 1 \n"+
			"\tAND OWNER = '%v' \n"+
			"\tAND TRIGGER_NAME = '%v'", v, s.Schema, s.Table)
		if result.BaseResult.TimeOut, f1, err = ExecSelectSql(ExecSqlInputS{
			Ss:           s,
			Event:        event,
			SelectSqlStr: result.BaseResult.Sql,
			Expect:       ETL.Map,
		}); err != nil || f1 == nil {
			continue
		}
		if err = global.MapSubToStructSubJsonName(mapNullActive(f1.(map[string]any)), &x); err != nil {
			return
		}
		x.Type = "trigger"
		x.PrintInfo = TriggerPrintInfo(&x)
		break
	}
	result.TriggerResult.Definition = x
	result.TriggerResult.Convert = triggerDefinitionConvert(x)
	return
}
